﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace SZHelperCore
{
    public class ConfigHelper : IDisposable
    {
        private string _configPath;
        private JsonNode _jsonNode;

        private FileSystemWatcher _watcher;
        private static readonly object padlock = new object();
        private bool _isSaving = false;

        public ConfigHelper(string configPath = "appsettings.json", bool isListenFile = false)
        {
            _configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configPath);
            Console.WriteLine(_configPath);

            if (File.Exists(_configPath))
            {
                ReloadFile();
            }
            else
            {
                _jsonNode = new JsonObject();
                SaveFile();
            }

            if (isListenFile)
            {
                ListenFile();
            }
        }

        private void SaveFile()
        {
            _isSaving = true;
            try
            {
                var options = new JsonSerializerOptions { WriteIndented = true };
                string json = _jsonNode.ToJsonString(options);
                File.WriteAllText(_configPath, json, System.Text.Encoding.UTF8);
            }
            finally
            {
                _isSaving = false;
            }
        }

        private void ReloadFile()
        {
            if (!File.Exists(_configPath)) return;

            string json = File.ReadAllText(_configPath, System.Text.Encoding.UTF8);
            _jsonNode = JsonNode.Parse(json) ?? new JsonObject();
        }

        private void ListenFile()
        {
            _watcher = new FileSystemWatcher
            {
                Path = Path.GetDirectoryName(_configPath)!,
                Filter = Path.GetFileName(_configPath),
                NotifyFilter = NotifyFilters.LastWrite
            };

            _watcher.Changed += (sender, e) =>
            {
                if (!_isSaving)
                {
                    // 防止频繁触发，简单延迟处理（可选增强）
                    System.Threading.Thread.Sleep(100); // 避免文件未释放
                    ReloadFile();
                }
            };

            _watcher.EnableRaisingEvents = true;
        }

        public string Get(string type, string key, string defaultValue = "")
        {
            bool isWrite = false;
            var root = (JsonObject)_jsonNode;

            if (!root.ContainsKey(type) || root[type] is not JsonObject)
            {
                root[type] = new JsonObject();
                isWrite = true;
            }

            var typeObj = (JsonObject)root[type];

            if (!typeObj.ContainsKey(key))
            {
                typeObj[key] = defaultValue;
                isWrite = true;
            }

            if (isWrite)
            {
                SaveFile();
            }

            return typeObj[key]?.ToString() ?? defaultValue;
        }

        public Dictionary<string, string> Gets(string type)
        {
            bool isWrite = false;
            var root = (JsonObject)_jsonNode;

            if (!root.ContainsKey(type) || root[type] is not JsonObject)
            {
                root[type] = new JsonObject();
                isWrite = true;
            }

            if (isWrite)
            {
                SaveFile();
            }

            var typeObj = (JsonObject)root[type];
            var result = new Dictionary<string, string>();

            foreach (var prop in typeObj)
            {
                result[prop.Key] = prop.Value?.ToString() ?? string.Empty;
            }

            return result;
        }

        public void Set(string type, string key, string value)
        {
            var root = (JsonObject)_jsonNode;

            if (!root.ContainsKey(type) || root[type] is not JsonObject)
            {
                root[type] = new JsonObject();
            }

            var typeObj = (JsonObject)root[type];
            typeObj[key] = value;

            SaveFile();
        }

        public void Dispose()
        {
            _watcher?.Dispose();
        }
    }
}